home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Telnet / NCSA / tn3270 2.4d7 source / NCSA⁄BYU TCP⁄IP / util.c < prev    next >
Text File  |  1991-11-27  |  25KB  |  1,169 lines

  1.  
  2. /*#define NEW_STUFF 1     /* BYU - changed to "MacTCPdriver" in make file. */
  3.  
  4.  
  5. /*
  6. *   Util.c
  7. *   utility library for use with the Network kernel
  8. *
  9. *   version 2, full session layer, TK started 6/17/87
  10. *
  11. ****************************************************************************
  12. *                                                                          *
  13. *      part of:                                                            *
  14. *      Network kernel for NCSA Telnet                                      *
  15. *      by Tim Krauskopf                                                    *
  16. *                                                                          *
  17. *      National Center for Supercomputing Applications                     *
  18. *      152 Computing Applications Building                                 *
  19. *      605 E. Springfield Ave.                                             *
  20. *      Champaign, IL  61820                                                *
  21. *                                                                          *
  22. *    Copyright (c) 1987, Board of Trustees of the University of Illinois   *
  23. *                                                                          *
  24. ****************************************************************************
  25. */
  26. #include <OSUtils.h>
  27. #include <stdio.h>
  28. #include "whatami.h"
  29. #include "hostform.h"
  30. #include "confile.h"
  31. #include "userd.h"
  32. #include "tools.h"
  33. #include "bkgr.h"
  34. #include <MacTCPCommonTypes.h>
  35. #include <AddressXlation.h>
  36.  
  37.  
  38.  
  39. #ifdef MAC
  40. #include <String.h>
  41. #include <Memory.h>
  42. #include "macutil.h"
  43. #endif
  44.  
  45. #ifdef PC
  46. #include <string.h>
  47. #else
  48. #ifdef AZTEC
  49. #define strchr(A,B) index(A,B)
  50. #endif
  51. #endif
  52.  
  53. extern void putln(),userftpd();    /* BYU */
  54. char                             /* special function types */
  55.             *neterrstring();
  56. int32 time();                    /* don't forget this sucker! */
  57.  
  58. extern struct machinfo *Sns;
  59.  
  60. static unsigned char
  61.             *Ssstemps[] = {
  62.             "capfile",
  63.             "hp.out",
  64.             "ps.out",
  65.             "tek.out"
  66.             };
  67.  
  68. char Sptypes[NPORTS];        /* port types assigned for session use */
  69.  
  70.  
  71. extern struct config Scon;        /* hardware configuration */
  72.  
  73. #define NTIMES 30
  74.  
  75. /*
  76. *  timer queue of events which will be placed into the event queue
  77. *  when the time is up.
  78. */
  79. struct {
  80.     unsigned char
  81.         eclass,                    /* event queue data */
  82.         event;
  83.     int
  84.         next,                    /* next item in list */
  85.         idata;
  86.     int32 when;                /* when timer is to go off */
  87. } Stq[NTIMES];
  88.  
  89.  
  90. struct DNRstruct {
  91.         struct machinfo *m;
  92.         Boolean done;
  93.         };
  94.  
  95. static int
  96.         domwait = 0,            /* is domain waiting for nameserver? */
  97.         Stfirst,Stfree;            /* pointers for timer queue */
  98.  
  99. #define PFTP 1
  100. #define PRCP 2
  101. #define PDATA 3
  102. #define PDOMAIN 4
  103.  
  104. /**************************************************************************/
  105. /*  Stask
  106. *   A higher level version of netsleep
  107. *
  108. *   This manages the timer queue
  109. */
  110.  
  111. static int32 recent=0L;
  112.  
  113. void Stask
  114.   (
  115.     void
  116.   )
  117.     {
  118.     long t;
  119.     int i;
  120.  
  121. #ifndef APPLE_DRIVERS
  122.     netsleep(0);
  123. #endif APPLE_DRIVERS
  124.  
  125. /*
  126. *  Check the timer queue to see if something should be posted
  127. *  First check for timer wraparound
  128. */
  129.     t = time(NULL);
  130. #ifdef PC
  131.     if (t < recent) {
  132.         i = Stfirst;
  133.         while (i >= 0) {
  134.             Stq[i].when -= WRAPTIME;
  135.             i = Stq[i].next;
  136.         }
  137.     }
  138. #endif
  139.     recent = t;                            /* save most recent time */
  140.  
  141.     while (Stfirst >= 0 && t > Stq[Stfirst].when) {        
  142.                                 /* Q is not empty and timer is going off */
  143.         i = Stfirst;
  144.         netputevent(Stq[i].eclass,Stq[i].event,Stq[i].idata);
  145.         Stfirst = Stq[Stfirst].next;    /* remove from q */
  146.         Stq[i].next = Stfree;
  147.         Stfree = i;                        /* add to free list */
  148.     }
  149.  
  150.  
  151. }
  152.  
  153. /************************************************************************/
  154. /*  Snetinit
  155. *   Do network initialization for those who want the defaults all
  156. *   set for them.  Recommend that neterrchange be called before
  157. *   initializing network stuff.
  158. */
  159. int Snetinit
  160.   (
  161.     void
  162.   )
  163.     {
  164.     int i;
  165.  
  166. /*
  167. *  set up the file names
  168. */
  169.     Scon.capture = Ssstemps[0];
  170.     Scon.hpfile = Ssstemps[1];
  171.     Scon.psfile = Ssstemps[2];
  172.     Scon.tekfile = Ssstemps[3];
  173.  
  174.     neteventinit();                /* initializes for error messages to count */
  175.  
  176.     for (i=0; i<NPORTS; i++)
  177.         Sptypes[i] = -1;            /* clear port type flags */
  178.  
  179.     for (i=0; i<NTIMES; i++)
  180.         Stq[i].next = i+1;            /* load linked list */
  181.     Stq[NTIMES-1].next = -1;        /* anchor end */
  182.     Stfirst = -1;
  183.     Stfree = 0;
  184.  
  185.     if (!Sreadhosts()) {             /* parses config file */
  186. #ifdef PC
  187.         netparms(Scon.irqnum,Scon.address,Scon.ioaddr);
  188. #endif
  189.         netconfig(Scon.hw);
  190.  
  191.         if (!netinit()) {            /* starts up hardware */
  192. /*
  193. *  Check for the need to RARP and do it
  194. */
  195.             netgetip(Scon.myipnum);    /* get stored ip num */
  196.             if (comparen(Scon.myipnum,"RARP",4)) {    /* need RARP */
  197.                 if (netgetrarp())    /* stores in nnipnum at lower layer */
  198.                     return(-2);
  199.                 netgetip(Scon.myipnum);
  200.                 netsetip(Scon.myipnum);    
  201.             }
  202.  
  203. /*
  204. *  Give the lower layers a chance to check to see if anyone else
  205. *  is using the same ip number.  Usually generates an ARP packet.
  206. */
  207.             netarpme(Scon.myipnum);        
  208.  
  209.             Ssetgates();            /* finishes IP inits */
  210.             Stask();
  211.             return(0);
  212.         }
  213.     }
  214.  
  215.     return(-1);    
  216. } /* Snetinit */
  217.  
  218. /**************************************************************************/
  219. /*  Stimerset
  220. *  Sets an asynchronous timer which is checked in Stask()
  221. *  usage:
  222. *  Time is in seconds
  223. *  Stimerset(class,event,dat,time)
  224. *    int class,event,dat,time;
  225. *    class,event,dat is the event which should be posted at the specified
  226. *    time.  Accuracy is dependent on how often Stask is called.
  227. */
  228.  
  229. int Stimerset
  230.   (
  231.     int class,
  232.     int event,
  233.     int dat,
  234.     int howlong
  235.   )
  236.     {
  237.     int i,j,jlast,retval;
  238.     int32 gooff;
  239.  
  240.     retval = 0;
  241.     gooff = time(NULL) + howlong;
  242.  
  243.     if (Stfree < 0) {                /* queue is full, post first event */
  244.         Stfree = Stfirst;
  245.         Stfirst = Stq[Stfirst].next;
  246.         Stq[Stfree].next = -1;
  247.         netputevent(Stq[Stfree].eclass,Stq[Stfree].event,Stq[Stfree].idata);
  248.         retval = -1;
  249.     }
  250.  
  251.     Stq[Stfree].idata = dat;                /* event to occur at that time */
  252.     Stq[Stfree].event = event;
  253.     Stq[Stfree].eclass = class;
  254.     Stq[Stfree].when = gooff;
  255.     i = Stfree;                            /* remove from free list */
  256.     Stfree = Stq[i].next;
  257.  
  258.     if (Stfirst < 0) {                    /* if no queue yet */
  259.         Stfirst = i;
  260.         Stq[i].next = -1;                /* anchor active q */
  261.     }
  262.  
  263.     else if (gooff < Stq[Stfirst].when) {    /* goes first on list */
  264.         Stq[i].next = Stfirst;                /* at beginning of list */
  265.         Stfirst = i;
  266.     }
  267.  
  268.     else {                                    /* goes in middle */
  269.  
  270.         j = jlast = Stfirst;                /* search q from beginning */
  271.  
  272.         while (gooff >= Stq[j].when && j >= 0) {
  273.             jlast = j;
  274.             j = Stq[j].next;
  275.         }
  276.         Stq[i].next = j;                    /* insert in q */
  277.         Stq[jlast].next = i;
  278.     }
  279.  
  280.     return(retval);
  281. }
  282.  
  283. /**************************************************************************/
  284. /*  Snetopen
  285. *
  286. *   Takes a pointer to a machine record, looked up with Sgethost and
  287. *   initiates the TCP open call.
  288. *
  289. */
  290. int Snetopen
  291.   (
  292.     struct machinfo *m,
  293.     int tport
  294.   )
  295.     {
  296.     int j;
  297.  
  298.     if (!m || m->mstat < HAVEIP)
  299.         return(-1);
  300.  
  301.     j = netxopen((uint32 *) m->hostip,tport,m->retrans,m->mtu,m->maxseg,m->window);
  302.                                     /* do the open call */
  303.  
  304.     if (j >= 0) {
  305.         Sptypes[j] = -1;            /* is allocated to user */
  306.         Stimerset(CONCLASS,CONFAIL,j,m->conto);
  307.         Stimerset(SCLASS,RETRYCON,j,m->retrans/TICKSPERSEC+2);
  308.     }
  309.  
  310.     return(j);
  311. }
  312.  
  313.  
  314. /**************************************************************************/
  315. /*
  316. *  special domain data structures
  317. */
  318. #define DOMSIZE 512                /* maximum domain message size to mess with */
  319.  
  320. /*
  321. *  Header for the DOMAIN queries
  322. *  ALL OF THESE ARE BYTE SWAPPED QUANTITIES!
  323. *  We are the poor slobs who are incompatible with the world's byte order
  324. */
  325. struct dhead {
  326. uint16
  327.     ident,                /* unique identifier */
  328.     flags,    
  329.     qdcount,            /* question section, # of entries */
  330.     ancount,            /* answers, how many */
  331.     nscount,            /* count of name server RRs */
  332.     arcount;            /* number of "additional" records */
  333. };
  334.  
  335. /*
  336. *  flag masks for the flags field of the DOMAIN header
  337. */
  338. #define DQR        0x8000            /* query = 0, response = 1 */
  339. #define DOPCODE    0x7100            /* opcode, see below */
  340. #define DAA        0x0400            /* Authoritative answer */
  341. #define DTC        0x0200            /* Truncation, response was cut off at 512 */
  342. #define DRD        0x0100            /* Recursion desired */
  343. #define DRA        0x0080            /* Recursion available */
  344. #define DRCODE    0x000F            /* response code, see below */
  345.  
  346.                                 /* opcode possible values: */
  347. #define DOPQUERY    0            /* a standard query */
  348. #define DOPIQ        1            /* an inverse query */
  349. #define DOPCQM        2            /* a completion query, multiple reply */
  350. #define DOPCQU        3             /* a completion query, single reply */
  351. /* the rest reserved for future */
  352.  
  353.                                 /* legal response codes: */
  354. #define DROK    0                /* okay response */
  355. #define DRFORM    1                /* format error */
  356. #define DRFAIL    2                /* their problem, server failed */
  357. #define DRNAME    3                /* name error, we know name doesn't exist */
  358. #define DRNOPE    4                /* no can do request */
  359. #define DRNOWAY    5                /* name server refusing to do request */
  360.  
  361. #define DTYPEA    1                /* host address resource record (RR) */
  362. #define DTYPEPTR    12            /* a domain name ptr */
  363.  
  364. #define DIN        1                /* ARPA internet class */
  365. #define DWILD    255                /* wildcard for several of the classifications */
  366.  
  367. /*
  368. *  a resource record is made up of a compressed domain name followed by
  369. *  this structure.  All of these ints need to be byteswapped before use.
  370. */
  371. struct rrpart {
  372.     uint16
  373.         rtype,                    /* resource record type = DTYPEA */
  374.         rclass;                    /* RR class = DIN */
  375.     uint32
  376.         rttl;                    /* time-to-live, changed to 32 bits */
  377.     uint16
  378.         rdlength;                /* length of next field */
  379.     uint8
  380.         rdata[DOMSIZE];            /* data field */
  381. };
  382.  
  383. /*
  384. *  data for domain name lookup
  385. */
  386. struct useek {
  387.     struct dhead h;
  388.     uint8 x[DOMSIZE];
  389. } question;
  390.  
  391. qinit()
  392.     {
  393.     question.h.flags = intswap(DRD);
  394.     question.h.qdcount = intswap(1);
  395.     question.h.ancount = 0;
  396.     question.h.nscount = 0;
  397.     question.h.arcount = 0;
  398. }
  399.  
  400.  
  401. /*********************************************************************/
  402. /*  packdom
  403. *   pack a regular text string into a packed domain name, suitable
  404. *   for the name server.
  405. */
  406. packdom(dst,src)
  407.     char *src,*dst;
  408.     {
  409.     char *p,*q,*savedst;
  410.     int i,dotflag,defflag;
  411.  
  412.     p = src;
  413.     dotflag = defflag = 0;
  414.     savedst = dst;
  415.  
  416.     do {                            /* copy whole string */
  417.         *dst = 0;
  418.         q = dst + 1;
  419.  
  420. /*
  421. *  copy the next label along, char by char until it meets a period or
  422. *  end of string.
  423. */
  424.         while (*p && (*p != '.')) 
  425.             *q++ = *p++;
  426.  
  427.         i = p - src;
  428.         if (i > 0x3f)
  429.             return(-1);
  430.         *dst = i;
  431.         *q = 0;
  432.  
  433.         if (*p) {                    /* update pointers */
  434.             dotflag = 1;
  435.             src = ++p;
  436.             dst = q;
  437.         }
  438.         else if (!dotflag && !defflag && Scon.defdom) {
  439.             p = Scon.defdom;        /* continue packing with default */
  440.             defflag = 1;
  441.             src = p;
  442.             dst = q;
  443.             netposterr(801);        /* using default domain */
  444.         }
  445.  
  446.     } while (*p);
  447.  
  448.     q++;
  449.     return(q-savedst);            /* length of packed string */
  450. }
  451.  
  452. /*********************************************************************/
  453. /*  unpackdom
  454. *  Unpack a compressed domain name that we have received from another
  455. *  host.  Handles pointers to continuation domain names -- buf is used
  456. *  as the base for the offset of any pointer which is present.
  457. *  returns the number of bytes at src which should be skipped over.
  458. *  Includes the NULL terminator in its length count.
  459. */
  460. unpackdom(dst,src,buf)
  461.     char *src,*dst,buf[];
  462.     {
  463.     int i,j,retval;
  464.     char *savesrc;
  465.  
  466.     savesrc = src;
  467.     retval = 0;
  468.  
  469.     while (*src) {
  470.         j = *src;
  471.  
  472.         while ((j & 0xC0) == 0xC0) {
  473.             if (!retval)
  474.                 retval = src-savesrc+2;
  475.             src++;
  476.             src = &buf[(j & 0x3f)*256+*src];        /* pointer dereference */
  477.             j = *src;
  478.         }
  479.  
  480.         src++;
  481.         for (i=0; i < (j & 0x3f) ; i++)
  482.             *dst++ = *src++;
  483.  
  484.         *dst++ = '.';
  485.     }
  486.  
  487.     *(--dst) = 0;            /* add terminator */
  488.     src++;                    /* account for terminator on src */
  489.  
  490.     if (!retval)
  491.         retval = src-savesrc;
  492.  
  493.     return(retval);
  494. }
  495.  
  496. /*********************************************************************/
  497. /*  sendom
  498. *   put together a domain lookup packet and send it
  499. *   uses port 53
  500. */
  501. sendom(s,towho,num)
  502.     char *s,*towho;
  503.     int16 num;
  504.     {
  505.     uint16 i,ulen;
  506.     uint8 *psave,*p;
  507.  
  508.     psave = (uint8 *)question.x;
  509.  
  510.     i = packdom(question.x,s);
  511.  
  512. /*
  513. *  load the fields of the question structure a character at a time so
  514. *  that 68000 machines won't barf.
  515. */
  516.     p = &question.x[i];
  517.     *p++ = 0;                /* high byte of qtype */
  518.     *p++ = DTYPEA;            /* number is < 256, so we know high byte=0 */
  519.     *p++ = 0;                /* high byte of qclass */
  520.     *p++ = DIN;                /* qtype is < 256 */
  521.  
  522.     question.h.ident = intswap(num);
  523.     ulen = sizeof(struct dhead)+(p-psave);
  524.  
  525.     netusend(towho, 53, 997, (unsigned char *) &question, ulen);
  526.     
  527. }
  528.  
  529.  
  530. pascal void DNRDone(hostInfoPtr,DNR)
  531. struct hostInfo *hostInfoPtr;
  532. struct DNRstruct *DNR;
  533. {
  534.     DNR->m->mstat = HAVEIP; 
  535.     putln("got to DNRdone");
  536.     if (!hostInfoPtr->rtnCode)            /* no error, so open it up */
  537.     {
  538.         movebytes(DNR->m->hostip,hostInfoPtr->addr,4);
  539.         netputevent(USERCLASS,DOMOK,DNR->m->mno);
  540.     }
  541.     else
  542.         netputevent(USERCLASS,DOMFAIL,DNR->m->mno); /* cant find ip # */
  543.     DNR->done = true;
  544.     DisposPtr((char *)DNR);
  545.     DisposPtr((char *)hostInfoPtr);
  546.     putln("got past DNRdone");
  547.  
  548. }
  549.  
  550.  
  551.  
  552.  
  553. /**************************************************************************/
  554. /*  Sdomain
  555. *   DOMAIN based name lookup
  556. *   query a domain name server to get an IP number
  557. *    Returns the machine number of the machine record for future reference.
  558. *   Events generated will have this number tagged with them.
  559. *   Returns various negative numbers on error conditions.
  560. */
  561. int Sdomain
  562.   (
  563.     char *mname
  564.   )
  565. {
  566. struct machinfo    *m;
  567.  
  568. #ifdef MacTCPdriver                        /* BYU */
  569. OSErr            theError;
  570. struct hostInfo    *myHost;
  571. Boolean            done;
  572. int                i;
  573. struct DNRstruct *DNRstuff;
  574. #endif                                    /* BYU */
  575.  
  576. #ifndef MacTCPdriver                    /* BYU 2.4.7 - was "#ifdef NEW_STUFF" */
  577.     if (!Sns)                             /* no nameserver, give up now */
  578.         return(-1);
  579. #endif
  580.  
  581.     while (*mname && *mname < 33)        /* kill leading spaces */
  582.         mname++;
  583.     if (!(*mname))
  584.         return(-1);
  585.  
  586.     if (!(m = Smadd(mname)))
  587.         return(-1);                        /* adds the number to the machlist */
  588.  
  589.     if (domwait < Scon.domto)
  590.         domwait = Scon.domto;            /* set the minimum timeout */
  591.     
  592. #ifdef MacTCPdriver                        /* BYU - was NEW_STUFF */
  593.  
  594.     DNRstuff = (struct DNRstruct *) NewPtr(sizeof(struct DNRstruct));
  595.     myHost = (struct hostInfo *) NewPtr(sizeof(struct hostInfo)*2);
  596.  
  597.     putln("Going to try to get domain name");    
  598.     putln("\n");
  599.     for (i = 0; i < NUM_ALT_ADDRS; i++)
  600.         myHost->addr[i] = 0;
  601.     done = false;
  602.     if (!m->hname) m->hname = m->sname;        /* BYU - patch received from Scott@NCSA. */
  603.     DNRstuff->m = m;
  604.     DNRstuff->done = done;
  605.     theError = StrToAddr(m->hname,myHost,DNRDone,(Ptr)DNRstuff);
  606.     
  607.     if (theError != cacheFault) DNRDone(myHost,DNRstuff);
  608.     m->mstat = HAVEIP;
  609. #else
  610.  
  611.     qinit();                            /* initialize some flag fields */
  612.     netulisten(997);                    /* pick a return port */
  613.     if (!m->hname)
  614.         m->hname = m->sname;            /* copy pointer to sname */
  615.     sendom(m->hname,Sns->hostip,m->mno);    /* try UDP */
  616.     Stimerset(SCLASS,UDPTO,m->mno,domwait);    /* time out quickly first time */
  617.     m->mstat = UDPDOM;
  618. #endif
  619.  
  620.     return(m->mno);
  621.   }
  622.  
  623. /*********************************************************************/
  624. /*  ddextract
  625. *   extract the ip number from a response message.
  626. *   returns the appropriate status code and if the ip number is available,
  627. *   copies it into mip
  628. */
  629. int ddextract
  630.   (
  631.     struct useek *qp,
  632.     unsigned char *mip
  633.   )
  634. {
  635. uint16 i,j,nans,rcode;
  636. struct rrpart *rrp;
  637. uint8 *p,space[260];
  638.  
  639.     nans = intswap(qp->h.ancount);                /* number of answers */
  640.     rcode = DRCODE & intswap(qp->h.flags);        /* return code for this message*/
  641.     if (rcode > 0)
  642.         return(rcode);
  643.  
  644.     if (nans > 0 &&                                /* at least one answer */
  645.         (intswap(qp->h.flags) & DQR)) {            /* response flag is set */
  646.         p = (uint8 *)qp->x;                    /* where question starts */
  647.         i = unpackdom(space,p,qp);                /* unpack question name */
  648. /*  spec defines name then  QTYPE + QCLASS = 4 bytes */
  649.         p += i+4;
  650. /*
  651. *  at this point, there may be several answers.  We will take the first
  652. *  one which has an IP number.  There may be other types of answers that
  653. *  we want to support later.
  654. */
  655.         while (nans-- > 0) {                    /* look at each answer */
  656.             i = unpackdom(space,p,qp);            /* answer name to unpack */
  657. /*            n_puts(space);*/
  658.             p += i;                                /* account for string */
  659.             rrp = (struct rrpart *)p;            /* resource record here */
  660. /*
  661. *  check things which might not align on 68000 chip one byte at a time
  662. */
  663.             if (!*p && *(p+1) == DTYPEA &&         /* correct type and class */
  664.                 !*(p+2) && *(p+3) == DIN) {
  665.                 movebytes(mip,rrp->rdata,4);    /* save IP #         */
  666.                 return(0);                        /* successful return */
  667.             }
  668.             movebytes(&j,&rrp->rdlength,2);        /* 68000 alignment */
  669.             p += 10+intswap(j);                    /* length of rest of RR */
  670.         }
  671.     }
  672.  
  673.     return(-1);                        /* generic failed to parse */
  674. }
  675.  
  676. /****************************************************************************/
  677. /*  Stimerunset
  678. *   Remove all such timer events from the queue
  679. *   They must match all three fields, event, class and optional data
  680. *
  681. */
  682. int Stimerunset
  683.   (
  684.     unsigned char class,
  685.     unsigned char event,
  686.     int dat
  687.   )
  688. {
  689. int i,ilast,retval;
  690.  
  691.     retval = ilast = -1;
  692.     i = Stfirst;
  693.     while (i >= 0 ) {                    /* search list */
  694.  
  695.         if (Stq[i].idata == dat &&         /* this one matches */
  696.             Stq[i].eclass == class && Stq[i].event == event) {
  697.  
  698.             retval = 0;                    /* found at least one */
  699. /*
  700. * major bug fix -- if first element matched, old code could crash
  701. */
  702.             if (i == Stfirst) {
  703.                 Stfirst = Stq[i].next;            /* first one matches */
  704.                 Stq[i].next = Stfree;            /* attach to free list */
  705.                 Stfree = i;
  706.                 i = Stfirst;
  707.                 continue;                        /* start list over */
  708.             }
  709.             else {
  710.                 Stq[ilast].next = Stq[i].next;    /* remove this entry */
  711.                 Stq[i].next = Stfree;            /* attach to free list */
  712.                 Stfree = i;
  713.                 i = ilast;
  714.             }
  715.         }
  716.  
  717.         ilast = i;
  718.         i = Stq[i].next;
  719.     }
  720.  
  721.     return(retval);
  722. }
  723.  
  724. /*********************************************************************/
  725. /*  getdomain
  726. *   Look at the results to see if our DOMAIN request is ready.
  727. *   It may be a timeout, which requires another query.
  728. */
  729.  
  730. udpdom()
  731. {
  732. struct machinfo    *m;
  733. int                i,uret,num;
  734. char            *p;
  735.  
  736.     uret = neturead((char *) &question);
  737.  
  738.     if (uret < 0)
  739.     {
  740. /*        netputevent(USERCLASS,DOMFAIL,-1);  */
  741.         return(-1);
  742.     }
  743.  
  744.     num = intswap(question.h.ident);        /* get machine number */
  745. /*
  746. *  check to see if the necessary information was in the UDP response
  747. */
  748.     m = Slooknum(num);                /* get machine info record */
  749.     if (!m)
  750.     {
  751.         netputevent(USERCLASS,DOMFAIL,num);
  752.         return(-1);
  753.     }
  754.  
  755. /*
  756. *  got a response, so reset timeout value to recommended minimum
  757. */
  758.     domwait = Scon.domto;
  759.  
  760.     i = ddextract(&question,m->hostip);
  761.  
  762.     switch (i) {
  763.         case 3:                        /* name does not exist */
  764.             netposterr(802);
  765.             p = neterrstring(-1);
  766.             strncpy(p,m->hname,78);        /* what name */
  767.             netposterr(-1);
  768.             netputevent(USERCLASS,DOMFAIL,num);
  769.             Stimerunset(SCLASS,UDPTO,num);
  770.             return(-1);
  771.         case 0:                        /* we found the IP number */
  772.             Stimerunset(SCLASS,UDPTO,num);
  773.             m->mstat = DOM;            /* mark that we have it from DOMAIN */
  774.             netputevent(USERCLASS,DOMOK,num);
  775.             return(0);
  776.         case -1:                    /* strange return code from ddextract */
  777.             netposterr(803);
  778.             break;
  779.         default:
  780.             netposterr(804);
  781.             break;
  782.     }
  783.  
  784.     return(0);
  785.  
  786. }
  787.  
  788. /**************************************************************************/
  789. /*  domto
  790. *   Handle time out for DOMAIN name lookup
  791. *   Retry as many times as recommended by config file
  792. */
  793. domto(num)
  794. int num;
  795. {
  796. struct machinfo *m;
  797.  
  798.     m = Slooknum(num);
  799.     if (!m)
  800.         return(-1);
  801.  
  802.     if (m->mstat > UDPDOM + Scon.ndom) {    /* permanent timeout */
  803.         netputevent(USERCLASS,DOMFAIL,num);
  804.         return(-1);
  805.     }
  806.     else
  807.         m->mstat++;            /* one more timeout */
  808.     
  809.     if (domwait < 20)        /* exponential backoff */
  810.         domwait <<= 1;
  811.  
  812.     Snewns();                /* rotate to next nameserver */
  813.  
  814.     qinit();
  815.  
  816.     netulisten(997);                    /* pick a return port */
  817.     sendom(m->hname,Sns->hostip,num);        /* try UDP */
  818.  
  819.     Stimerset(SCLASS,UDPTO,num,domwait);    /* time out more slowly */
  820.  
  821.     return(num);
  822.     
  823. }
  824.  
  825.  
  826. /***********************************************************************/
  827. static int son=1;
  828.  
  829. Scwritemode(mode)
  830. int mode;
  831. {
  832.     son = mode;
  833.     return(0);
  834. }
  835.  
  836. /***********************************************************************/
  837. Scmode()
  838. {
  839.     return(son);
  840. }
  841.  
  842. /***********************************************************************/
  843. static int tekon=1;
  844.  
  845. void Stekmode
  846.   (
  847.     int mode
  848.   )
  849. int mode;
  850. {
  851.         tekon = mode;
  852. }
  853.  
  854. /***********************************************************************/
  855. Stmode()
  856. {
  857.     return(tekon);
  858. }
  859.  
  860. /***********************************************************************/
  861. #ifdef PC
  862. static int rcpon=1;
  863.  
  864. Srcpmode(mode)
  865. int mode;
  866. {
  867.     rcpon = mode;
  868.     if (rcpon)
  869.         setrshd();
  870.     else
  871.         unsetrshd();
  872.     return(0);
  873. }
  874.  
  875. /***********************************************************************/
  876. Srmode()
  877. {
  878.     return(rcpon);
  879. }
  880. #endif
  881.  
  882. /***********************************************************************/
  883. static int ftpon=0;
  884.  
  885. int Sftpmode
  886.   (
  887.     int mode
  888.   )
  889. {
  890.     if (ftpon && mode)
  891.         return(-1);
  892.  
  893.     ftpon = mode;
  894.     if (ftpon)
  895.         setftp();
  896.     else
  897.         unsetftp();
  898.     return(0);
  899. }
  900.  
  901. /***********************************************************************/
  902. int Sfmode
  903.   (
  904.     void
  905.   )
  906. {
  907.     return(ftpon);
  908. }
  909.  
  910. /***********************************************************************/
  911. /*  Snewcap
  912. *   set a new capture file name
  913. */
  914. int Snewcap
  915.   (
  916.     char *s
  917.   )
  918. {
  919.     if (NULL == (Scon.capture = NewPtr(strlen(s)+1)))
  920.         return(1);
  921.     strcpy(Scon.capture,s);
  922.     return(0);
  923. }
  924.  
  925. /***********************************************************************/
  926. /*  Snewps
  927. *   set a new ps file name
  928. */
  929. int Snewpsfile
  930.   (
  931.     char *s
  932.   )
  933. {
  934.     if (NULL == (Scon.psfile = NewPtr(strlen(s)+1)))
  935.         return(1);
  936.     strcpy(Scon.psfile,s);
  937.     return(0);
  938. }
  939.  
  940. /***********************************************************************/
  941. /*  Snewhpfile
  942. *   set a new HPGL file name
  943. */
  944. int Snewhpfile
  945.   (
  946.     char *s
  947.   )
  948. {
  949.     if (NULL == (Scon.hpfile = NewPtr(strlen(s)+1)))
  950.         return(1);
  951.     strcpy(Scon.hpfile,s);
  952.     return(0);
  953. }
  954.  
  955. /***********************************************************************/
  956. /*  Snewtekfile
  957. *   set a new tek file name
  958. */
  959. int Snewtekfile
  960.   (
  961.     char *s
  962.   )
  963. {
  964.     if (NULL == (Scon.tekfile = NewPtr(strlen(s)+1)))
  965.         return(1);
  966.     strcpy(Scon.tekfile,s);
  967.     return(0);
  968. }
  969.  
  970. /***********************************************************************/
  971. /*  Sopencap
  972. *   returns a file handle to an open capture file
  973. *   Uses the locally stored capture file name.
  974. */
  975. FILE *
  976. Sopencap()
  977. {
  978. FILE *retfp;
  979.  
  980.     if (NULL == (retfp = fopen(Scon.capture,"ab"))) 
  981.         return(NULL);
  982.  
  983.     fseek(retfp,0L,2);        /* seek to end */
  984.  
  985.     return(retfp);
  986. }
  987.  
  988. /****************************************************************************/
  989. /* Scompass
  990. *  compute and check the encrypted password
  991. */
  992. int Scompass
  993.   (
  994.     char *ps,
  995.     char *en
  996.   )
  997. {
  998. int ck;
  999. char *p,c;
  1000.  
  1001.     ck = 0;
  1002.     p = ps;
  1003.     while (*p)                /* checksum the string */
  1004.         ck += *p++;
  1005.  
  1006.     c = ck;
  1007.  
  1008.     while (*en) {
  1009.         if ((((*ps ^ c) | 32) & 127) != *en)    /* XOR with checksum */
  1010.             return(0);
  1011.         if (*ps)
  1012.             ps++;
  1013.         else
  1014.             c++;            /* increment checksum to hide length */
  1015.         en++;
  1016.     }
  1017.  
  1018.     return(1);
  1019. }
  1020.  
  1021. /****************************************************************************/
  1022. /*  Scheckpass
  1023. *   Check the password file for the user,password combination
  1024. *   Returns valid or invalid
  1025. */
  1026. int Scheckpass
  1027.   (
  1028.     char *us,
  1029.     char *ps
  1030.   )
  1031. char *us,*ps;
  1032. {
  1033. char buf[81],*p;
  1034. FILE *fp;
  1035.  
  1036.     if (NULL == (fp = fopen(Scon.pass,"r"))) {
  1037.     
  1038. #ifdef MAC
  1039. /*
  1040. *  failed open, so try to find file in the system folder.
  1041. */
  1042.  
  1043.         sysdir();                            /* change to system folder */
  1044.         fp = fopen(Scon.pass,"r");
  1045.         
  1046.         setmydir();                            /* reset back to default dir */
  1047.         
  1048.         if (NULL == fp)                        /* still didn't work? */
  1049. #endif
  1050.             return(0);
  1051.     }
  1052.  
  1053.     while (NULL != fgets(buf,80,fp)) {
  1054.         p = strchr(buf,'\n');
  1055.         *p = '\0';                            /* remove \n */
  1056.  
  1057.         p = strchr(buf,':');                /* find delimiter */
  1058.         *p++ = '\0';
  1059.         if (!strcmp(buf,us) &&            /* found user */
  1060.             Scompass(ps,p)) {            /* does password check ?*/
  1061.             fclose(fp);
  1062.             return(1);
  1063.         }
  1064.     }
  1065.  
  1066.     fclose(fp);
  1067.     return(0);
  1068. }
  1069.  
  1070. /****************************************************************************/
  1071. /* Sneedpass
  1072. *  For other routines to call and find out if a password is required
  1073. */
  1074. int Sneedpass
  1075.   (
  1076.     void
  1077.   )
  1078. {
  1079.     if (Scon.pass == NULL)
  1080.         return(0);
  1081.  
  1082.     return(1);
  1083. }
  1084.  
  1085. /****************************************************************************/
  1086. /*  Sgetevent
  1087. *   gets events from the network and filters those for session related
  1088. *   activity.  Returns any other events to the caller.
  1089. */
  1090. int Sgetevent
  1091.   (
  1092.     int class,
  1093.     int *what,
  1094.     int *datp
  1095.   )
  1096. {
  1097. int retval;
  1098.  
  1099.     if (retval = netgetevent(SCLASS,what,datp)) {    /* session event */
  1100.         switch (retval) {
  1101.             case FTPACT:
  1102.                 ftpd(0,*datp);
  1103.                 break;
  1104. #ifdef PC
  1105.             case RCPACT:                /* give CPU to rsh for rcp */
  1106.                 rshd(0);
  1107.                 break;
  1108. #endif
  1109. #ifdef MAC
  1110.             case CLOSEDONE:                /* Used in the drivers */
  1111.                 netclose( *datp);
  1112.                 break;
  1113.             case CLOSEDONE+1:                /* Used in the drivers */
  1114.                 netclose( *datp);
  1115.                 break;
  1116. #endif MAC
  1117.             case UDPTO:                    /* name server not responding */
  1118.                 domto(*datp);
  1119.                 break;
  1120.             case RETRYCON:
  1121.                 if (0 < netopen2(*datp))     /* connection open yet? */
  1122.                     Stimerset(SCLASS,RETRYCON,*datp,4);  /* 4 is a kludge */
  1123.                 break;
  1124.  
  1125.             default:
  1126.                 break;
  1127.         }
  1128.     }
  1129.  
  1130.     Stask();                        /* allow net and timers to take place */
  1131.  
  1132.     if (!(retval = netgetevent(class,what,datp)))
  1133.         return(0);
  1134.         
  1135.     if (retval == CONOPEN) 
  1136.         Stimerunset(CONCLASS,CONFAIL,*datp);   /* kill this timer */
  1137.  
  1138.     if ((*datp == 997) && (retval == UDPDATA)) {
  1139.         udpdom();
  1140.     }
  1141.     else if ((*what == CONCLASS) && (Sptypes[*datp] >= 0)) {
  1142.                                         /* might be for session layer */
  1143.         switch (Sptypes[*datp]) {
  1144.             case PFTP:
  1145.                 rftpd(retval);
  1146.                 break;
  1147.             case PDATA:
  1148.                 ftpd(retval,*datp);
  1149.                 break;
  1150.             case UDATA:                        /* BYU */
  1151.                 userftpd(retval,*datp);        /* BYU */
  1152.                 break;                        /* BYU */
  1153. #ifdef PC
  1154.             case PRCP:
  1155.                 rshd(retval);
  1156.                 break;
  1157. #endif
  1158.             default:
  1159.                 break;
  1160.         }
  1161.     }
  1162.     else
  1163.         return(retval);                /* let higher layer have it */
  1164.  
  1165.     return(0);
  1166. }
  1167.  
  1168.  
  1169.